package org.lc.platform.mybatis.crud.service.impl;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.PostConstruct;
import org.lc.platform.mybatis.crud.service.CrudBaseService;
import org.lc.platform.base.dto.PageQuery;
import org.lc.platform.base.exception.BusinessException;
import org.lc.platform.base.exception.SystemException;
import org.lc.platform.base.vo.PageVo;
import org.lc.platform.mybatis.entity.BaseEntity;
import org.lc.platform.mybatis.manager.EntityManager;
import org.lc.platform.mybatis.manager.query.QueryBuilder;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

public abstract class CrudBaseServiceImpl<D extends PageQuery, V, M extends BaseMapper<T>, T extends BaseEntity> extends ServiceImpl<M, T> implements CrudBaseService<D, T, V> {


    public EntityManager<T> manager;


    @PostConstruct
    public void initManager() {
        this.manager = new EntityManager<>(this.getEntityClass());
    }

    public QueryBuilder<T> getQueryBuilder(D query, QueryBuilder<T> queryBuilder) {
        return queryBuilder;
    }

    @Override
    public PageVo<V> getBaseMany(D query) {
        QueryBuilder<T> queryBuilder = getQueryBuilder(query, this.manager.createQueryBuilder());
        Page<T> page = query.toMapPage();
        Page<T> p = null;
        if (query.getIsPage()) {
            p = queryBuilder.relation(query.getJoin()).page(page);
        } else {
            p = new Page<>();
            p.setRecords(queryBuilder.relation(query.getJoin()).list());
        }
        return PageVo.of(p, this::Convertor);
    }

    @Override
    public V getBaseOne(String id, String join) {
        var data = this.manager.createQueryBuilder().eq("id", id)
                .relation(join)
                .one();

        return Convertor(data);
    }

    @Override
    public Boolean updateBaseOne(String id, T data) {
        var record = this.getById(id);
        if (record != null) {
            data.setVersion(record.getVersion());
            data.setId(id);
        }
        return this.updateById(data);
    }

    @Override
    public Boolean deleteBaseOne(String id) {
        return this.removeById(id);
    }

    @Override
    @Transactional
    public Boolean deleteBaseMany(List<String> ids) {
        try {
            String regex = "^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}$";
            boolean isFailed = ids.stream().anyMatch(r -> !r.matches(regex));
            if (isFailed) {
                throw new BusinessException("数组含有非法UUID");
            }
        } catch (Exception e) {
            throw new SystemException(e.getMessage());
        }
        return this.removeBatchByIds(ids);
    }

    @Override
    public Boolean createBaseOne(T body) {
        return this.save(body);
    }
}
